﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Jingstudio.WatermarkMaker.Watermark;
using Microsoft.Office.Interop.Excel;
using Ymatou.CommonService;
using Ymatou.File.Lib;
using FileHelper = Ymatou.File.Lib.FileHelper;
using Rectangle = System.Drawing.Rectangle;

namespace Ymatou.File.Controllers
{
    public class FileController : Controller
    {
        //
        // GET: /Download/
        public ActionResult Download(string type, string name, string source = "")
        {
            //验证权限

            //不再判断页面来源
            //if (!FileTool.ValidateRefUrl(type, Request))
            //{
            //    return HttpNotFound();
            //}


            //获取上传根路径
            string basePath = FileHelper.PhysicalBasePath;

            type = FileTool.GetPhysicalFolder(type, source);

            string filePath = Path.Combine(basePath, Path.Combine(type, name));

            if (System.IO.File.Exists(filePath))
            {
                string ext = Path.GetExtension(filePath);

                string contentType = "application/octet-stream";

                contentType = FileHelper.GetContentType(ext.TrimStart('.'));

                return File(filePath, contentType);
            }
            else
            {
                return HttpNotFound();
                //return Content(this.ErrorMessage("File Not Found"));
            }
        }

        /// <summary>
        ///     上传文件
        /// </summary>
        /// <param name="fname"></param>
        /// <param name="source">处理类型</param>
        /// <param name="type">文件类型</param>
        /// <param name="autoName">是否自动生成文件名</param>
        /// <returns></returns>
        [ValidateAuthorize]
        public string Upload(string fname, string type, string source = "", bool autoName = true)
        {
            if (fname != null && type != null)
            {
                if (Request.Files.Count <= 0)
                {
                    return this.ErrorMessage("没有文件");
                }

                try
                {
                    string basePath = FileHelper.PhysicalBasePath;

                    //根据文件类型确定存储路径
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "others";
                    }

                    //获取保存的文件夹
                    type = FileTool.GetPhysicalFolder(type, source);

                    //保存的文件名
                    string fileSaveName = fname.Trim();

                    //根据类型及文件名生成文件保存路径

                    if (autoName)
                    {
                        fname = FileTool.GenerateFileName(fname);
                    }
                    string fileMapPath = Path.Combine(type, fname);
                    FileTool.SaveFile(Request.InputStream, Path.Combine(basePath, fileMapPath));

                    return FileTool.GenerateAccessUrl(fileMapPath);
                }
                catch (Exception)
                {
                    return this.ErrorMessage("保存文件出错");
                }
            }
            else
            {
                return this.ErrorMessage("参数不匹配");
            }
        }


        /// <summary>
        ///     上传文件转换格式为excel 2010
        /// </summary>
        /// <param name="fname"></param>
        /// <param name="format">xlExcel12--excel 2010;xlExcel8--excel 2003</param>
        /// <returns></returns>
        [ValidateAuthorize]
        [ValidateInput(false)]
        public ActionResult ConverExcelFormat(string fname, string format = "xlExcel8")
        {
            try
            {
                if (fname == null)
                {
                    throw new Exception("参数不匹配");
                }
                var extension = string.Empty;
                var targetFormat = XlFileFormat.xlExcel12;
                switch (format.ToLower())
                {
                    case "xlexcel12":
                        targetFormat = XlFileFormat.xlOpenXMLWorkbook;
                        extension = ".xlsx";
                        break;
                    case "xlexcel8":
                        targetFormat = XlFileFormat.xlExcel8;
                        extension = ".xls";
                        break;
                    default:
                        throw new NotSupportedException("暂不支持该类型");
                }
                string basePath = FileHelper.PhysicalBasePath;
                var subDirectory = string.Format(@".\Excel\{0}", DateTime.Now.ToString("yyyyMMdd"));
                var fileName = Path.GetFileName(fname);
                //save origin file
                var fileExtension = Path.GetExtension(fname);
                var randomFileName = Guid.NewGuid().ToString("N");
                string orignFilePath = Path.Combine(basePath, subDirectory, randomFileName + fileExtension);
                FileTool.SaveFile(Request.InputStream, orignFilePath);
                //convert
                string saveFilePath = Path.Combine(basePath, subDirectory, randomFileName + "new" + extension);
                try
                {
                    var excel = new Application
                                    {
                                        Interactive = false,
                                        DisplayAlerts = false
                                    };
                    var workbook = excel.Workbooks.Open(orignFilePath);
                    workbook.SaveAs(saveFilePath, targetFormat);
                    workbook.Close();
                    excel.Quit();
                }
                catch (Exception ex)
                {
                    ApplicationLog.Debug("formate" + targetFormat);
                    ApplicationLog.Debug("saveFilePath" + saveFilePath);
                    throw;
                }
                //return 
                return File(saveFilePath, "application/ms-excel", Path.GetFileName(saveFilePath));
            }
            catch (Exception ex)
            {
                ApplicationLog.Error("Excel转换出现异常", ex);
                throw;
            }
        }

        /// <summary>
        ///     修改图片大小
        /// </summary>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="source"></param>
        /// <param name="dest"></param>
        /// <returns></returns>
        [ValidateAuthorize]
        [TypeExsits]
        public string ResizePic(string type, string name, float x, float y, float width, float height, float widthZipRate, float heightZipRate, int targetWidth, int targetHeight, string source = "", string dest = "resize")
        {
            string basePath = FileHelper.PhysicalBasePath;

            string folderSource = FileTool.GetPhysicalFolder(type, source);

            string fileSourcePath = Path.Combine(basePath, Path.Combine(folderSource, name));

            if (!System.IO.File.Exists(fileSourcePath))
            {
                return this.ErrorMessage("当前图片未能找到");
            }

            Image image = null;
            Bitmap bmImage = null;
            try
            {
                //生成保存的图片
                string targetFolder = FileTool.GetAndGeneratePhysicalFolder(type, dest);
                string mapPath = Path.Combine(targetFolder, name);
                string targetPath = Path.Combine(basePath, mapPath);

                if (System.IO.File.Exists(targetPath))
                {
                    ApplicationLog.Info("ResizePic删除文件：" + targetPath + "请求IP：" + ClientInfo.GetClientIp());
                    System.IO.File.Delete(targetPath);
                }

                //计算保存区域
                int realX = (int) (x/widthZipRate);
                int realY = (int) (y/heightZipRate);
                int realWidth = (int) (width/widthZipRate);
                int realHeight = (int) (height/heightZipRate);

                //按保存区域保存图片
                image = Image.FromFile(fileSourcePath);
                bmImage = new Bitmap(targetWidth, targetHeight, PixelFormat.Format24bppRgb);
                bmImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

                Graphics graphics = Graphics.FromImage(bmImage);
                graphics.DrawImage(image, new Rectangle(0, 0, targetWidth, targetHeight), realX, realY, realWidth, realHeight, GraphicsUnit.Pixel);
                bmImage.Save(targetPath, ImageFormat.Jpeg);

                image.Dispose();
                bmImage.Dispose();
                graphics.Dispose();

                return FileTool.GenerateAccessUrl(mapPath);
            }
            catch (Exception e)
            {
                ApplicationLog.Error("修改图片尺寸出现异常", e);

                return this.ErrorMessage(e.Message);
            }
        }

        /// <summary>
        ///     添加mapSource,用于指定需要真实修正的图片，source为当前图片，mapSource为原图片
        /// </summary>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="quotiety"></param>
        /// <param name="mapSource"></param>
        /// <param name="source"></param>
        /// <param name="dest">保存的目标文件夹</param>
        /// <returns></returns>
        [TypeExsits]
        [ValidateAuthorize]
        public string ResizePicWithMap(string type, string name, float x, float y, float width, float height, float widthZipRate, float heightZipRate, int targetWidth, int targetHeight, string mappedSource, string source = "", string dest = "resize")
        {
            string basePath = FileHelper.PhysicalBasePath;

            string folderMap = FileTool.GetPhysicalFolder(type, mappedSource);

            string fileMapPath = Path.Combine(basePath, Path.Combine(folderMap, name));

            if (!System.IO.File.Exists(fileMapPath))
            {
                return this.ErrorMessage("源图片未能找到");
            }

            string folderSource = FileTool.GetPhysicalFolder(type, source);

            string fileSourcePath = Path.Combine(basePath, Path.Combine(folderSource, name));

            if (!System.IO.File.Exists(fileSourcePath))
            {
                return this.ErrorMessage("当前图片未能找到");
            }

            try
            {
                using (Image sourceImg = Image.FromFile(fileSourcePath))
                {
                    using (Image mapImg = Image.FromFile(fileMapPath))
                    {
                        float widthRate = mapImg.Width/(float) sourceImg.Width;
                        float heightRate = mapImg.Height/(float) sourceImg.Height;

                        //修正源图片上的位移
                        x = x/widthRate;
                        y = y/heightRate;

                        width = width/widthRate;
                        height = height/heightRate;

                        //widthZipRate = widthZipRate * widthRate;
                        //heightZipRate = heightZipRate * heightRate;

                        mapImg.Dispose();
                        sourceImg.Dispose();
                    }
                }
            }
            catch (Exception e)
            {
                ApplicationLog.Error("修改图片尺寸出现异常", e);

                return this.ErrorMessage(e.Message);
            }

            return ResizePic(type, name, x, y, width, height, widthZipRate, heightZipRate, targetWidth, targetHeight, source, dest);
        }

        /// <summary>
        ///     获取图片预览图
        /// </summary>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <param name="maxWidth"></param>
        /// <param name="maxHeight"></param>
        /// <param name="source"></param>
        /// <param name="dest"></param>
        /// <returns></returns>
        [ValidateAuthorize]
        [TypeExsits]
        public string GetPreviewPic(string type, string name, int maxWidth, int maxHeight, string source = "", string dest = "preview")
        {
            string basePath = FileHelper.PhysicalBasePath;

            string folderSource = FileTool.GetPhysicalFolder(type, source);

            string fileSourcePath = Path.Combine(basePath, Path.Combine(folderSource, name));

            if (!System.IO.File.Exists(fileSourcePath))
            {
                return this.ErrorMessage("源图片未能找到");
            }

            if (maxWidth <= 0)
            {
                maxWidth = 700;
            }

            if (maxHeight <= 0)
            {
                maxHeight = 400;
            }

            try
            {
                string fileMapPath = Path.Combine(FileTool.GetAndGeneratePhysicalFolder(type, dest), name);

                string fileSavePath = Path.Combine(basePath, fileMapPath);

                if (System.IO.File.Exists(fileSavePath))
                {
                    ApplicationLog.Info("GetPreviewPic删除文件：" + fileSavePath + "请求IP：" + ClientInfo.GetClientIp());
                    System.IO.File.Delete(fileSavePath);
                }

                int width = 0;
                int height = 0;

                bool needOperate = false;
                using (Image image = Image.FromFile(fileSourcePath))
                {
                    // 等比例缩放
                    width = image.Width;
                    height = image.Height;

                    if (image.Width > maxWidth || image.Height > maxHeight)
                    {
                        needOperate = true;

                        float floatWidth = (float) image.Width;
                        float floatHeight = (float) image.Height;

                        if (floatWidth > floatHeight)
                        {
                            floatWidth = (float) maxWidth;
                            floatHeight = (floatWidth/(float) image.Width)*(float) image.Height;
                        }
                        else
                        {
                            floatHeight = (float) maxHeight;
                            floatWidth = (floatHeight/(float) image.Height)*(float) image.Width;
                        }

                        width = (int) floatWidth;
                        height = (int) floatHeight;
                        using (Bitmap bmImage = new Bitmap(width, height, PixelFormat.Format24bppRgb))
                        {
                            bmImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

                            // 创建Graphics对象
                            Graphics graphics = Graphics.FromImage(bmImage);
                            //graphics.Dispose();

                            graphics.DrawImage(image, new Rectangle(0, 0, width, height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);

                            bmImage.Save(fileSavePath, ImageFormat.Jpeg);
                            graphics.Dispose();
                            bmImage.Dispose();
                            image.Dispose();
                        }
                    }
                }

                if (!needOperate)
                {
                    System.IO.File.Copy(fileSourcePath, fileSavePath);
                }

                return FileTool.GenerateAccessUrl(fileMapPath) + "#" + width + "&" + height;
            }
            catch (Exception e)
            {
                ApplicationLog.Error("获取图片预览图出现异常", e);

                return this.ErrorMessage(e.Message);
            }
        }

        /// <summary>
        ///     为图片添加水印
        /// </summary>
        /// <param name="type">文件类型</param>
        /// <param name="name">文件名</param>
        /// <param name="fmark">水印图片名，默认文件夹watermark</param>
        /// <param name="source">原文件图片类型</param>
        /// <param name="dest">保存的文件图片类型</param>
        /// <returns></returns>
        [ValidateAuthorize]
        [TypeExsits]
        public string AddWaterMark(string type, string name, string fmark, string source = "", string dest = "")
        {
            string folderSource = FileTool.GetPhysicalFolder(type, source);

            string fileSourcePath = Path.Combine(FileHelper.PhysicalBasePath, Path.Combine(folderSource, name));

            if (!System.IO.File.Exists(fileSourcePath))
            {
                return this.ErrorMessage("源图片未能找到");
            }

            try
            {
                if (source == dest)
                {
                    //生成的图片需要覆盖源图片，先将原图片拷入临时文件
                    string tempPath = Path.Combine(FileHelper.PhysicalBasePath, FileTool.GetAndGeneratePhysicalFolder("temp"), name);

                    System.IO.File.Copy(fileSourcePath, tempPath, true);

                    fileSourcePath = tempPath;
                }

                string waterMarkFilePath = Path.Combine(FileHelper.PhysicalBasePath, FileHelper.WaterMarkFolder, fmark);

                if (!System.IO.File.Exists(waterMarkFilePath))
                {
                    return this.ErrorMessage("水印图片不存在");
                }

                //添加水印
                ImageWatermark imgWaterMark = new ImageWatermark();
                imgWaterMark.SetImageProperty(waterMarkFilePath, 80);
                imgWaterMark.SetPosition(ContentAlignment.BottomLeft, 0, 10);
                Watermarker watermarker = Watermarker.Instance(new Watermark[]
                                                                   {
                                                                       imgWaterMark
                                                                   });
                
                string virtualPath = Path.Combine(FileTool.GetAndGeneratePhysicalFolder(type, dest), name);
                string savePath = Path.Combine(FileHelper.PhysicalBasePath, virtualPath);

                bool result = watermarker.Save(fileSourcePath, savePath);

                if (result)
                {
                    return FileTool.GenerateAccessUrl(virtualPath);
                }
                else
                {
                    return this.ErrorMessage("添加水印失败");
                }
            }
            catch (Exception e)
            {
                ApplicationLog.Error("添加水印出现异常", e);

                return this.ErrorMessage(e.Message);
            }
        }

        /// <summary>
        ///     删除文件
        /// </summary>
        /// <param name="fname"></param>
        /// <param name="type"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        [ValidateAuthorize]
        [TypeExsits]
        public string DeleteFile(string name, string type, string source = "")
        {
            string folderSource = FileTool.GetPhysicalFolder(type, source);

            string fileSourcePath = Path.Combine(FileHelper.PhysicalBasePath, Path.Combine(folderSource, name));

            try
            {
                if (System.IO.File.Exists(fileSourcePath))
                {

                    ApplicationLog.Info("DeleteFile删除文件：" + fileSourcePath + "请求IP：" + ClientInfo.GetClientIp());
                    System.IO.File.Delete(fileSourcePath);
                }

                return "";
            }
            catch (Exception e)
            {
                ApplicationLog.Error("删除文件出现异常", e);

                return this.ErrorMessage(e.Message);
            }
        }

        [ValidateAuthorize]
        [TypeExsits]
        public string CreatePdfFromUrl(string url, string type, bool autoName = true, string fileName = "")
        {
            try
            {
                if (autoName || (!autoName && string.IsNullOrEmpty(fileName)))
                {
                    fileName = "pdf.pdf";

                    fileName = FileTool.GenerateFileName(fileName);
                }

                string fileMapPath = Path.Combine(FileTool.GetAndGeneratePhysicalFolder(type), fileName);

                string fileSavePath = Path.Combine(FileHelper.PhysicalBasePath, fileMapPath);

                if (System.IO.File.Exists(fileSavePath))
                {
                    ApplicationLog.Info("CreatePdfFromUrl删除文件：" + fileSavePath + "请求IP：" + ClientInfo.GetClientIp());
                    System.IO.File.Delete(fileSavePath);
                }

                ComponentLib.CreatePdfByHtml(url, fileSavePath);

                return FileTool.GenerateAccessUrl(fileMapPath);
            }
            catch (Exception e)
            {
                ApplicationLog.Error("生成PDF出现异常", e);

                return this.ErrorMessage(e.Message);
            }
        }
    }
}